package com.chenyanqing.sqlsession;

import com.chenyanqing.config.Configuration;
import com.chenyanqing.config.ExecuteSQLType;
import com.chenyanqing.pojo.MapperStatement;

import java.lang.reflect.*;
import java.util.List;

public class DefaultSqlSession implements  SqlSession {



    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration){
        this.configuration = configuration;
    }

    @Override
    public <T> List<T> selectList(String statementId, Object... objects) throws Exception {
        SimplerExecutor executor = new SimplerExecutor();
        return executor.query(configuration,configuration.getMap().get(statementId),objects);
    }

    @Override
    public <T> T selectOne(String statementId, Object... objects) throws Exception {
        List<Object> objects1 = selectList(statementId, objects);
        if(objects1==null || objects1.size()==0){
            return null;
        }
        if(objects1.size()==1){
            return (T)objects1.get(0);
        }
        throw  new  RuntimeException("查询结果是多个");

    }

    @Override
    public Integer update(String statementId, Object... objects) throws Exception {
        SimplerExecutor executor = new SimplerExecutor();
        return executor.update(configuration,configuration.getMap().get(statementId),objects);
    }


    @Override
    public Integer insert(String statementId, Object... objects) throws Exception {
        SimplerExecutor executor = new SimplerExecutor();
        return executor.update(configuration,configuration.getMap().get(statementId),objects);
    }


    @Override
    public Integer delete(String statementId, Object... objects) throws Exception {
        SimplerExecutor executor = new SimplerExecutor();
        return executor.update(configuration,configuration.getMap().get(statementId),objects);
    }

    @Override
    public <T> T getMapper(Class<?> maaperClass) {

        //使用jdk动态代理生成代理对象
        Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{maaperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //底层还是执行jdbc代码，根据不同情况调用select或者update或者delete方法

                //1、准备statementid，namespace和id的拼接==接口全限定名.方法名,//2获取方法的类名的字节码对象
                String name = method.getName();
                String className = method.getDeclaringClass().getName();
                String statementId = className+"."+name;

                //准备参数args
                Type genericReturnType = method.getGenericReturnType();
                //根据sql类型走不同的excute逻辑
                return invokeExecuteSql(statementId,genericReturnType,args);
            }
        });
        return (T) proxyInstance;
    }



    private Object invokeExecuteSql(String statementId,  Type genericReturnType,Object[]args) throws Exception {

        MapperStatement statement = configuration.getMap().get(statementId);
        if(statement==null){
            throw new RuntimeException("no bind statement");
        }

        ExecuteSQLType defaultSqlType = statement.getExecuteSQLType();
        switch (defaultSqlType){
            case SELECT:
                {
                //判断是否是范型类型参数化，如果有范型 认为是集合，否则认为是实体对象
                if (genericReturnType instanceof ParameterizedType) {
                    List<Object> objects = selectList(statementId,args );
                    return objects;
                } else {
                    return selectOne(statementId, args);
                }
                }
            case DELETE:
                return delete(statementId, args);


            case UPDATE:
                return update(statementId, args);

            case INSERT:
                return insert(statementId, args);
            default:
                return  selectList(statementId,args );
        }


    }

}
